<html>
<head>
  <title>更加深入</title>
  <basefont face="微软雅黑" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="YXBJ Windows/602628 (zh-CN, DDL); Windows/10.0.0 (Win64); EDAMVersion=V2;"/>
  <style>
    body, td {
      font-family: 微软雅黑;
      font-size: 10pt;
    }
  </style>
</head>
<body>
<a name="29472"/>
<h1>更加深入</h1>
<div>
<table bgcolor="#D4DDE5" border="0">
<tr><td><b>创建时间：</b></td><td><i>2021/1/20 6:11</i></td></tr>
<tr><td><b>更新时间：</b></td><td><i>2021/3/11 1:06</i></td></tr>
<tr><td><b>作者：</b></td><td><i>YuGe</i></td></tr>
</table>
</div>
<br/>

<div>
<span><div><div><span style="font-size: 18pt;">定义设计模式</span></div><ul><li><div>模式是在某情境（context）下，针对某问题的某种解决方案。</div></li><ul><li><div><span style="font-weight: bold;">情境</span>就是应用某个模式的情况，这应该是会不断出现的情况。</div></li><li><div><span style="font-weight: bold;">问题</span>就是你想在某情境下达到的目标，但也可以是某情境下的约束。</div></li><li><div><span style="font-weight: bold;">解决方案</span>就是你所追求的：一个通用的设计，用来解决约束、达到目标。</div></li></ul><li><div>如果你发现自己处于某个情境下，面对着所欲达到的目标被一群约束影响着的问题，然而，你能够应用某个设计，克服这些约束并达到该目标，将你领向某个解决方案。</div></li><li><div>一个设计模式是解决一个经常重复发生的设计问题。</div></li><li><div>我们采用一种规矩的方式描述模式，就能为模式创建出“类目”。而这个类目能为我们带来各种好处。</div></li><li><div>模式应该具备的几个条件：</div></li><ul><li><div>必须能够应用于一个重复出现的问题。</div></li><li><div>其他人应该也可以应用这个模式来解决相同的问题。</div></li><li><div>模式应该拥有名字：如果没有名字，一个模式就无法变成开发人员之间共享的词汇。</div><div>名称非常重要！当每个模式都有一个名称的时候，我们谈论起模式来就相当容易了；也就是说，大家会有一个共享的词汇。</div></li></ul><li><div>真实世界中的很多实例，都不符合经典的设计模式。模式只是指导方针，可以改变模式来符合自己的需要。</div><div>然而，当你在改变模式的时候，最好能够在文档中注明它与经典的设计模式有何差异。这样一来，其他的开发人员就能够很快地认出你用的这个模式，并了解两者的差异。</div></li></ul><div><span style="font-size: 18pt;">设计模式的类目</span></div><ul><li><div>描述一个模式：模式类目：描述某个模式的意图、动机、可能应用该模式的地方、解决方案的设计以及使用后果（好的或坏的）。</div></li><li><div>如何获得模式类目：</div></li><ul><li><div>《设计模式：可复用面向对象软件的基础》列出了23个基本模式的类目。</div></li><li><div>还有许多其他将焦点放在不同领域（例如：企业软件、并发系统、业务系统）的模式类目。</div></li></ul><li><div>类目内容：</div><div>每个模式的描述方式都遵照一个模板，并阐述该模式的许多细节。</div></li><ul><li><div>名称</div></li><li><div>意图：简短的描述该模式的作用。描述该模式是什么，有点像定义，可以理解成定义。</div></li><li><div>动机：给出了问题以及如何解决这个问题的具体场景。</div></li><li><div>适用性：描述模式可以被应用在什么场合。</div></li><li><div>结构：提供了图示（类图、对象图等），显示出参与此模式的类之间的关系。描述类图内的所有组成模式的类的设计，以及每个类扮演的角色。</div></li><li><div>参与者：描述在此设计中涉及到的类和对象在模式中的责任和角色。</div></li><li><div>协作：告诉我们参与者如何在此模式中合作。</div></li><li><div>结果：描述采用此模式之后可能产生的效果：好的与不好的。</div></li><li><div>实现：提供了你在实现该模式时需要使用的技巧，以及你应该小心面对的问题。</div></li><li><div>范例代码：提供代码的片段，可能对自己的实现有帮助。描述如何实现这个模式，而且通常由展示怎么做的范例代码。</div></li><li><div>已知应用：描述已经在真实系统中发现的模式例子。告诉我们在真实的系统中，这个模式会使用在何处。</div></li><li><div>相关模式：描述了此模式和其他的模式之间的关系。</div></li></ul><li><div>如何使用类目</div></li><ul><li><div><span style="font-size: unset; color: unset; font-family: unset;">遇到问题时，如何翻阅类目寻找解决方案：</span></div></li><ul><li><div>首先，试着让自己熟悉所有的模式以及它们之间的关系。</div></li><li><div>然后，当需要一个模式的时候，大概就知道是什么模式。应参考描述动机和适用性的小节，确认的想法没错。还有一个很重要的小节：结果。浏览这个模式的“结果”，确保该模式不会给我的设计带来意外的影响。</div></li></ul><li><div>一旦知道某个模式是正确的，对这个模式的应用和实现：</div></li><ul><li><div>此时需要类图。先是阅读“结构”这一节，以了解类图，然后看“参与者”这节，确定我了解每一个类的角色。</div></li><li><div>接下来，就可以开始进行自己的设计，做出符合自己需求的一些更改，并继续阅读“实现/范例代码”小节，以确认我知道可能会遇到的所有较好的实现技巧。</div></li></ul></ul></ul><div><span style="font-size: 18pt;">发掘自己的设计模式</span></div><ul><li><div>首先，请务必牢记在心，模式是被“发现的”，而不是被创建的。所以，任何人都可能发现某个设计模式，然后写出它的描述。</div></li><li><div>应有意愿：你应该先想想看为何你想发现自己的模式—一大多数的人都不是“编写”模式，只是使用模式。</div></li><ul><li><div>你可能是在某一个特定的领域中工作，而你认为新的模式将大有帮助</div></li><li><div>你找到个解决方案，能够解决一个再三出现的问题</div></li><li><div>你只是想要加入设计模式的社群贡献自己的力量。</div></li></ul><li><div>如何开始</div></li><ul><li><div>就像任何原则一样，你知道得越多越好。</div><div>先研究已经被发现的这些模式，了解它们做了些什么，并弄清楚它们和其他模式之间的关系。这些准备工作非常重要，不但可以让你熟悉模式是如何打造出来的，也可以避免做多余的工作。</div></li><li><div>完成这些准备工作之后，你可以开始将你的模式写在纸上，以便与其他开发人员沟通。</div></li></ul><li><div>如何知道自己是否真的发现了一个设计模式：</div></li><ul><li><div>除非其他人使用它并且发现它很有用，否则你并不算拥有一个模式。</div></li><li><div>一般来说，必须要通过“三次规则”，才算是一个合格的模式。也就是说，只有在真实的世界中被应用三次以上，才能算是一个模式。</div></li></ul><li><div>发掘自己的设计模式的方法和步骤</div></li><ul><li><div>做好家庭作业</div><div>在发掘新的模式之前，你必须先精通现有的模式。许多模式看起来像是全新的，但是事实上只是现有模式的变种。通过研究现有的模式，你可以比较容易地识别模式，并且学会将某一模式与其他模式联系起来。</div></li><li><div>花时间反思与评估</div></li><ul><li><div>反思：你的经验（你所遭遇过的问题，以及采取的解决方案）正是模式想法的来源。所以，花时间反思过去的经验，并将它用在以后的新设计上面。</div></li><li><div>评估：请牢记，大多数的模式都是现有模式的变种，而非崭新的模式。而且当你真的找到了好像是新模式的东西时，常常都局限在很窄的适用性中，而不能称得上是一个真正的模式。</div></li></ul><li><div>将你的想法写在纸上，好让其他人能够理解</div><div>如果其他人不能够使用你所找到的模式，那么这个新模式作用也就不大；你需要将你的“准模式”写成一份文档，好让其他人能够阅读、理解，并采用它来解决他们自己的问题，然后将使用的心得反馈给你。</div><div>很幸运的是，你不需要发明自己的模式归档方法，你可以直接采用四人组的模板</div></li><li><div>让其他人使用你的模式，然后再持续改进</div><div>不要认为你可以一次就把模式搞定，应该要把模式当成是随着时间不断进步的一项工程。让其他人评审你的准模式，并尝试着使用它，然后将意见反馈给你。将这些反馈汇总到你的描述中，再重复上述的步骤。你的描述永远不会是完美的，但是到了某个时间点之后，就会相当地稳固，足以让其他开发人员能够阅读并理解它。</div><div>使用已有的模式模板定义你的模式，因为这些模板已经包含了许多智慧，而且其他的模式用户也认识这样的格式。</div></li><li><div>不要忘了三次原则</div><div>请记住，除非你的模式已经在真实世界的三个方案中被成功地采用了，否则就不够资格被当成模式。所以，当别人能够使用你的模式，并将意见反馈给你时，你就有机会能够将它变成一个实用的模式。</div></li></ul></ul><div><span style="font-size: 18pt;">设计模式的分类</span></div><ul><li><div>随着发掘的设计模式数目逐渐增加，有必要将它们分级分类，好将它们组织起来，以简化我们寻找模式的过程，并让同一群组内的模式互相比较。</div></li><li><div>模式的意图并不相同，而这通常是了解某个模式属于哪个类目时的关键。</div></li><li><div>类目可以让我们思考模式群组之间的关系，以及同一组模式内模式之间的关系。</div></li><li><div>根据模式的目标分成三个不同类目：创建型、行为型和结构型。</div></li><ul><li><div>创建型</div><div>创建型模式涉及到将对象实例化，这类模式都提供一个方法，将客户从所需要实例化的对象中解耦。</div></li><li><div>行为型</div><div>只要是行为型模式，都涉及到类和对象如何交互及分配职责。</div><div>行为型模式的目的是对象之间的沟通与互连。</div></li><li><div>结构型</div><div>结构型模式可以让你把类或对象组合到更大的结构中。</div><div>结构型模式用来描述类和对象如何被组合以建立新的结构或新的功能。</div></li></ul><li><div>模式还有另一种分类方式：模式所处理的是类或对象。</div></li><ul><li><div>类模式</div><div>类模式描述类之间的关系如何通过继承定义。类模式的关系是在编译时建立的。</div></li><li><div>对象模式</div><div>对象模式描述对象之间的关系，而且主要是利用组合定义。对象模式的关系通常在运行时建立，而且更加动态、更有弹性。</div></li><li><div>对象模式比类模式的数目多出许多。</div></li></ul><li><div>如果建立自己的分类方式可以帮你更加了解这些模式的话，那么你也可以这么做。</div></li><li><div>通过比较可让你对模式有清晰的概念，这是毋庸置疑的。但是许多人被创建型、结构型和行为型类目搞得一头雾水，常常发现某个模式似乎不只适合一个类目。请记住，怎么分类并不重要，重要的是了解这些模式和它们之间的关系。只要类目有帮助，我们就用它，反之就不用。</div></li><li><div>通过分类，我们可以将一组模式视为一个群体。当我们需要一个创建型模式，但又不知道确切是哪一个的时候，就可以用创建型模式这个词来统称它。</div><div>而且分类也有助于我们比较相同类目内的其他成员。</div></li></ul><div><span style="font-size: 18pt;">使用设计模式的方法</span></div><ul><li><div>下面是一份快速指南，可以帮助你开始“用模式思考”。所谓“用模式思考”，意思是说，能够看着设计，体会在什么地方模式能自然适用，在什么地方模式则不能。</div></li><ul><li><div>保持简单（ Keep It Simple/KISS）</div><div>首先，<span style="font-weight: bold;">当你设计时，尽可能地用最简单的方式解决问题。你的目标应该是简单，</span>而不是“如何在这个问题中应用模式”。千万不要认为：如果没有使用模式解决某个问题，就不是经验丰富的开发人员。正确的说法是，为了要让你的设计简单且有弹性，有时候使用模式是最好的方法。</div></li><li><div>设计模式非万是丹；事实上，连什么丹都算不上！</div><div>模式是解决一再发生的问题的通用方案。模式已经被许多开发人员实际测试过。所以，当你需要某个模式的时候，可以放心地使用它，毕竟你知道这个模式已经身经百战。</div><div>然而，模式并非万灵丹，要使用模式，你需要考虑到模式对你的设计中其他部分所造成的后果。</div></li><li><div>需要知道何时需要模式</div><div>当你在设计的时候，如果确定在你的设计中可以利用某个模式解决某个问题，那么就使用这个模式！如果有更简单的解决方案，那么在决定使用模式之前应该先考虑这个方案。</div><div>如何知道何时适用一个模式，这就需要经验和知识。一旦你确定一个简单的解决方案无法满足你的需要，应该考虑这个问题以及相关的约束——这可以帮你将问题对应到一个模式中。如果你对于模式有很深的认知，就可能知道有什么模式适合这样的情况。否则，就花些时间调査一下可能会解决这个问题的模式，模式类目中的意图和应用部分会特别有用。一旦找到了一个看起来适合的模式，要先确定你是否能接受这个模式所带来的后果，以及对设计其他部分的影响。</div><div>有一种情况，即使有更简单的解决方案，你仍然想要使用模式，这种情况就是：你预期系统在未来会发生改变。找出你的设计中会改变的区域，通常这是需要模式的迹象。但是务必要确定一件事：加入模式是要应对可能发生的实际改变，而不是假想的改变。</div><div><span style="font-size: unset; color: unset; font-family: unset;">并非只有在设计时才考虑引进模式，在重构（ refactoring）时也要这样做！</span></div></li><li><div>重构的时间就是模式的时间！</div><div>重构就是通过改变你的代码来改进它的组织方式的过程。目标是要改善其结构，而不是其行为。这是一个很好的时机，可以重新检查你的设计来看看是否能够利用模式让它拥有更好的结构。</div></li><li><div>拿掉你所不需要的，不要害将一个<span style="font-size: unset; color: unset; font-family: unset;">设</span>计模式从你的设计中删除。</div><div>当你的系统变得非常复杂，而且并不需要预留任何弹性的时候，就不要使用模式。换句话说，也就是当一个较简单的解决方案比使用模式更恰当的时候。</div></li><li><div>如果你现在不需要，就别做。</div><div><span style="font-size: unset; color: unset; font-family: unset;">设计模式威力很强大，你很容易就可以在当前设计中看到模式的各种应用方式。开发人员天生就热爱创建漂亮的架构以应对任何方向的改变。</span></div><div><span style="font-size: unset; color: unset; font-family: unset;">但如果你今天在设计中有实际的需要去支持改变，就放手采用模式处理这个改变吧！然而，如果说理由只是假想的，就不要添加这个模式，因为这只会将你的系统越搞越复杂，而且很可能你永远都不会需要它！</span></div><div>将你的思绪集中在设计本身，而不是在模式上。只有在真正需要时才使用模式。有些时候，简单的方式就行得通，那么就别用模式。</div></li></ul><li><div>模式只是一种工具，只有在需要时才使用这种工具。你也花了很多时间学习设计原则。一开始总是先遵循这些原则，建立最简单的代码以完成工作。<span style="font-size: unset; color: unset; font-family: unset;">在这个过程中，你看到有需要模式的地方，就使用模式。</span></div></li><li><div>“应用模式”绝对不是你开始设计时所该有的目标，应该让模式在你的设计过程中自然而然地出现。</div></li><li><div>模式可能带来复杂性，如果没有必要，我们绝不需要这样的复杂性。</div></li><li><div>当你确信你的设计中有一个问题需要解决的时候，或者当你确信未来的需求可能会改变时，都可以采用模式。</div></li><li><div>过度使用设计模式可能导致代码被过度工程化。<span style="font-weight: bold;">应该总是用最简单的解决方案完成工作，并在真正需要模式的地方才使用它。</span></div></li><li><div>设计模式不仅可以帮助你在大脑中装进这些解决方案，也可以让你和其他开发人员之间有共享的词汇，而这正是设计模式最大的优点之一。</div><div>共享词汇的五种方式</div></li><ul><li><div>在设计会议中：当你和你的团队在会议中讨论软件设计时，使用设计模式可以帮你们待在“设计中”久一点。从设计模式和面向对象原则的视角讨论设计，可以避免你的团队很快地陷入实现的细节，也可以避免发生许多误解。</div></li><li><div>和其他开发人员：当你和其他开发人员讨论的时候，可以使用模式。这可以帮助其他开发人员学习新模式，并建立一个社群。和别人分享你所学会的东西是很有成就感的一件事情。</div></li><li><div>在架构文档中：当你在编写架构文档的时候，使用模式将会缩减文档的篇幅，并且让读者更清楚地了解你的设计。</div></li><li><div>在代码注释以及命名习惯上：当你在编写代码的时候，应在注释中清楚地注明你所使用的模式。在选择类和方法的名称时，应尽可能显示出隐藏在下面的模式。其他的开发人员在阅读你的代码时会感激你，因为你让他们能够很快地了解你的实现。</div></li><li><div>将志同道合的开发人员集合在一起：分享你的知识。许多开发人员都听说过模式，但并不真正了解什么是模式。你可以自愿为他们讲一堂模式介绍课，或者成立一个读书会。</div></li></ul></ul><div><span style="font-size: 24px;">反模式</span></div><ul><li><div>反模式告诉你如何采用一个不好的解决方案解决一个问题。</div></li><li><div>反模式看起来总像是个好的解决方案，但是当它真正被采用后，就会带来麻烦。</div></li><li><div>通过将反模式归档，我们能够帮助其他人在实现它们之前，分辨出不好的解决方案。</div></li><li><div>如果老是有人用某个不好的解决方案处理某个问题，而通过将它归档，可以帮助其他开发人员避免犯同样的错误。毕竟，避免不好的解决方案，就和发现好的解决方案一样有价值！</div></li><li><div>一个反模式的元素：</div></li><ul><li><div>反模式告诉我们为什么不好的解决方案会有吸引力。</div></li><li><div>必须面对的是，如果不好的解决方案没有任何吸引力，那么根本就不会有人想要使用它。反模式最重要的工作之一，在于警告你不要陷入某种致命的诱惑。</div></li><li><div>反模式告诉你为何这个解决方案从长远看会造成不好的影响。</div></li><li><div>为了了解为什么这是一个反模式，你必须了解它在将来如何造成负面影响。反模式会告诉你使用这个解决方案，在将来会为你带来怎样的麻烦。</div></li><li><div>反模式建议你改用其他的模式以提供更好的解决方案。</div></li><li><div>反模式除了告诉你什么解决方案不好之外，也会为你指出正确的方向，向你建议一些会引向好的解决方案的可能性，这样反模式才真正有帮助。</div></li></ul></ul><div><span style="font-size: 24px;">个人想法</span></div><ul><li><div>很多设计模式都是通过增加一个中间层来解决问题！</div></li><li><div>说实话感觉自己只是知道了设计模式，但是对设计模式的理解并不深，最关键的是总感觉并没有理解每种设计模式的核心。就连常用的设计模式的核心也没有理解！比如为什么这么称呼，应用场景的关键是什么，使用的关键特征是什么等。如果不理解这些，就没有办法做调整，做针对应用场景的修正。</div></li></ul><div><br/></div></div><div><br/></div></span>
</div></body></html> 